// background.ts
import { BASE_URL } from "@/constants/request";
import {
  getRandomUserAgent,
  sleep,
  formatTime,
  removeUrlSearchParams,
  sendMessage,
  customDeepClone,
} from "@/utils/tools";
import {
  MAX_PARSE_HTML_COUNT,
  MAX_DEAL_IMAGE_COUNT,
} from "@/constants/collect";
import type { TAsinDataMap } from "@/type/content";
import { CHUNK_LENGTH } from "@/constants/collect";
import AsyncTaskPool from "@/class/AsyncTaskPool";
import type {
  CollectConfig,
  TCollectCountMap,
  TMultiKeywordCollectData,
  TAsinUrlMap,
} from "@/type/collect";
import PollingManager from "@/class/PollingManager";
import ConcurrentExecutor from "@/class/ConcurrentExecutor";

interface HtmlResponse {
  code: number;
  data: string[];
}

interface Html {
  getHtmlNew(
    url: string,
    options: { signal: any },
    callback: (response: string) => void
  ): void;
  postHtmlNew(
    url: string,
    options: { data: { url: string }; httpType: string },
    callback: (response: HtmlResponse) => void
  ): void;
}

const SERVICE_WORKER_CLOSE_DELAY = 1000;

let activeTabIds: number[] = [];
let collectCountMap: TCollectCountMap = {
  current: 0,
  total: 0,
  failed: 0,
  skipped: 0,
};
let collectResultList: any[] = [];
const abortControllerMap: {
  [key: number]: any;
} = {};
let isCollecting = false;
function afterStartCollect() {
  if (!isCollecting) {
    collectResultList = [];
    isCollecting = true;
    // 向 App.vue 发送采集开始标记
    sendMessage({
      action: "collectStatusChange",
      status: "start",
    });
  }
}

function sendToContentScript({ action, data }: { action: string; data?: any }) {
  // 步骤1：获取目标标签页的 tabId（例如：当前活跃标签页）
  chrome.tabs.query({}, (tabs) => {
    tabs.forEach((tab) => {
      if (tab.id && activeTabIds.includes(tab.id)) {
        chrome.tabs.sendMessage(tab.id, {
          action,
          data: customDeepClone(data || {}),
        });
      }
    });
  });
}

function collectCountTotalChange(changeValue: number) {
  collectCountMap.total += changeValue;
  sendToContentScript({
    action: "changeCollectCount",
    data: {
      collectCountMap,
    },
  });
}
function addCollectCountSkipped(changeValue: number) {
  if (collectCountMap.total) {
    collectCountMap.skipped += changeValue;
    sendToContentScript({
      action: "changeCollectCount",
      data: {
        collectCountMap,
      },
    });
  }
}
function addCollectCountFailed(changeValue: number) {
  if (collectCountMap.total) {
    collectCountMap.failed += changeValue;
    sendToContentScript({
      action: "changeCollectCount",
      data: {
        collectCountMap,
      },
    });
  }
}
function addCollectCountCurrent(changeValue: number) {
  if (collectCountMap.total) {
    collectCountMap.current += changeValue;
    sendToContentScript({
      action: "changeCollectCount",
      data: {
        collectCountMap,
      },
    });
  }
}

function finishCollect() {
  isCollecting = false;
  // 重置商品数
  collectCountMap = {
    current: 0,
    total: 0,
    failed: 0,
    skipped: 0,
  };
  const isRunning = asyncTaskPool.isRunning();
  if (isRunning) {
    asyncTaskPool.stop();
  }
  // 向 App.vue 发送采集结束标记
  sendMessage({
    action: "collectStatusChange",
    status: "end",
  });
}

function endCollectChangeButtonHtml() {
  sendToContentScript({
    action: "endCollectChangeButtonHtml",
    data: {
      collectCountMap,
    },
  });
  finishCollect();
}

function cancelCollectChangeButtonHtml() {
  sendToContentScript({
    action: "cancelCollectChangeButtonHtml",
    data: {
      collectCountMap,
    },
  });
  finishCollect();
}

function startCollectChangeButtonHtml() {
  sendToContentScript({
    action: "startCollectChangeButtonHtml",
  });
}

function collectCurrentPage({
  asinUrlMap,
  collectConfig,
  isRetry = false,
}: {
  asinUrlMap: TAsinUrlMap;
  collectConfig: CollectConfig;
  isRetry: boolean;
}) {
  // TODO ZCH 调试
  // const asinUrlMapEntriesList = Object.entries(asinUrlMap).slice(0, 2);
  const asinUrlMapEntriesList = Object.entries(asinUrlMap);
  const length = asinUrlMapEntriesList.length;

  if (!isRetry) {
    collectCountTotalChange(length);
  }

  const ainUrlMapByClaimTemplate = asinUrlMapEntriesList.reduce(
    (obj: any, item: any) => {
      const [key, value] = item;
      const { claimTemplate }: { url: string; claimTemplate: string } = value;
      if (claimTemplate) {
        if (!obj[claimTemplate]) {
          obj[claimTemplate] = {};
        }
        obj[claimTemplate][key] = value;
      }

      return obj;
    },
    {}
  );
  const chunkedList: [string, TAsinDataMap][][] = [];
  Object.values(ainUrlMapByClaimTemplate).forEach(
    (asinUrlMapByClaimTemplateItem: any) => {
      const list = Object.entries(asinUrlMapByClaimTemplateItem);
      for (let i = 0; i < list.length; i += CHUNK_LENGTH) {
        chunkedList.push(
          list.slice(i, i + CHUNK_LENGTH) as [string, TAsinDataMap][]
        );
      }
    }
  );

  chunkedList.forEach((chunkItemList) => {
    asyncTaskPool.push(() => {
      return sendCollectGoodsToContent({
        chunkItemList,
        collectConfig,
      });
    });
  });
}

const asyncTaskPool = new AsyncTaskPool(
  MAX_PARSE_HTML_COUNT,
  endCollectChangeButtonHtml
); // 同时请求解析接口

// Define Html and s objects or fetch them from somewhere
const Html: Html = {
  getHtmlNew: (url, options, callback) => {
    // Example implementation using fetch
    const headers = {
      "User-Agent": getRandomUserAgent(),
      "Accept-Language":
        Math.random() > 0.5 ? "en-US,en;q=0.9" : "en-GB,en;q=0.8",
    };
    let response: Response | null = null;
    const signal = options?.signal;
    fetch(url, {
      headers,
      signal,
    })
      .then((res) => {
        response = res;
        // 获取内容长度（字节），200KB = 200 * 1024 字节
        const contentLength = res.headers.get("content-length");
        const maxSize = 200 * 1024;

        if (contentLength && parseInt(contentLength, 10) < maxSize) {
          // 内容大小小于200KB时主动抛出错误
          throw new Error(
            `HTML size (${contentLength} bytes) is less than 200KB`
          );
        }

        return res.text();
      })
      .then((text) => {
        callback(text);
        // 清理 response 引用
        response = null;
      })
      .catch((error) => {
        console.error("Error fetching HTML:", error);
        // 确保清理 response 引用
        response = null;
      });
  },
  postHtmlNew: (url, options, callback) => {
    // Example implementation using fetch
    fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
      body: new URLSearchParams(options.data as any).toString(),
    })
      .then((response) => response.json())
      .then((data) => callback(data))
      .catch((error) => console.error("Error posting HTML:", error));
  },
};

async function uploadLogToAliyun(logs: any[]) {
  try {
    const storage = await chrome.storage.sync.get(["baoyiplus_userInfo"]);
    const baoyiUseId = storage?.baoyiplus_userInfo?.id || "";
    const url =
      "https://vue-collect-plugin-log.cn-hangzhou.log.aliyuncs.com/logstores/error-log/track";
    await fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        __source__: "vue-collect-plugin",
        __logs__: logs.map((log) => {
          return {
            ...log,
            baoyiUseId,
          };
        }),
      }),
    });
  } catch (e) {
    console.warn("upload log failed", e);
  }
}

function getTabInfo(tabId: number): Promise<chrome.tabs.Tab | false> {
  return new Promise((resolve) => {
    // 调用 tabs.get 尝试获取标签页
    chrome.tabs.get(tabId, (tab) => {
      // 检查是否有错误（tabId 不存在时会触发错误）
      if (chrome.runtime.lastError) {
        // 错误信息通常包含 "No tab with id" 等关键词
        resolve(false); // tabId 不存在
      } else {
        resolve(tab); // tabId 存在
      }
    });
  });
}

async function waitForTab(
  tabId: number,
  timeout = 15000,
  interval = 500
): Promise<boolean> {
  const start = Date.now();
  return new Promise((resolve) => {
    const checkTab = async () => {
      if (activeTabIds.includes(tabId)) {
        await sleep(500);
        resolve(true);
      } else if (Date.now() - start > timeout) {
        resolve(false); // 超时
      } else {
        setTimeout(checkTab, interval);
      }
    };
    checkTab();
  });
}
async function getTabIdByUrl(url: string) {
  const length = activeTabIds.length;
  const urlParts = new URL(url);
  let matchTabId = 0;
  const unExistsTabs: number[] = [];
  for (let i = 0; i < length; i++) {
    const tabId = activeTabIds[i];
    const tabInfo = await getTabInfo(tabId);
    if (tabInfo && tabInfo.url) {
      const tabUrlParts = new URL(tabInfo.url);
      if (urlParts.origin === tabUrlParts.origin && !matchTabId) {
        matchTabId = tabId;
      }
    } else {
      unExistsTabs.push(tabId);
    }
  }

  activeTabIds = activeTabIds.filter((tabId) => {
    return !unExistsTabs.includes(tabId);
  });

  if (matchTabId) {
    return matchTabId;
  }

  const createTab = await chrome.tabs.create({
    url: url,
    active: true, // 是否激活新标签页（可选，默认 true）
  });
  // 获取 tabId
  const tabId = createTab.id;
  const rabReady = await waitForTab(tabId!);
  if (!rabReady) {
    throw new Error("等待新标签页加入 activeTabIds 超时");
  }
  if (tabId) {
    activeTabIds.push(tabId);
  }

  return tabId;
}

const getOssUrl = ({
  token,
  params,
  signal,
}: {
  token: string;
  params: any;
  signal: any;
}) => {
  return fetch(
    `${BASE_URL}/user-file/user/fileStorage/generatePresignedUploadUrls/collectUpload`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + token,
      },
      body: JSON.stringify({
        ...params,
      }),
      signal,
    }
  )
    .then((res) => {
      if (!res.ok) {
        throw new Error(`HTTP error! status: ${res.status}`);
      }
      return res.json();
    })
    .then((data) => {
      // 检查响应数据是否成功
      if (data.code !== 0 && data.code !== undefined) {
        throw new Error(
          data.msg || data.message || `Request failed with code: ${data.code}`
        );
      }
      return data;
    });
};

function createCheckTabCollectGoods(
  tabId: number,
  port: any,
  reject: (error: Error) => void
) {
  return async function checkTabCollectGoods() {
    if (!port) {
      // port 可能已经被清理，直接返回
      return;
    }
    const tabInfo = await getTabInfo(tabId);
    if (!tabInfo) {
      // 主动断开连接，这会触发 port.onDisconnect 监听器
      // onDisconnect 中的 reject 会处理 Promise 的拒绝
      port.disconnect();
      // 作为安全机制：如果 onDisconnect 没有被触发（理论上不应该发生），
      // 使用保存的 reject 函数来确保 Promise 被 reject
      if (reject) {
        setTimeout(() => {
          reject(new Error("标签已被关闭"));
        }, 100);
      }
    }
  };
}

async function sendCollectGoodsToContent(data: any) {
  return new Promise((resolve, reject) => {
    let isResolved = false; // 标记 Promise 是否已被 resolve/reject，防止重复处理
    let port: any = null; // 每个任务独立的 port
    let checkTabCollectGoodsPolling: PollingManager | null = null; // 每个任务独立的轮询实例
    let closePromise: Promise<void> | null = null; // 避免重复调用 self.close

    const { chunkItemList } = data;

    const scheduleServiceWorkerClose = () => {
      if (closePromise) {
        return closePromise;
      }

      // Service Worker 需要短暂延迟后再关闭，避免频繁激活/挂起抖动
      closePromise = sleep(SERVICE_WORKER_CLOSE_DELAY)
        .then(() => {
          try {
            if (typeof self !== "undefined") {
              const swGlobal = self as typeof globalThis & {
                close?: () => void;
              };
              swGlobal.close?.();
            }
          } catch (error) {
            // 忽略关闭时可能抛出的异常
          }
        })
        .catch(() => {
          // sleep 不会 reject，这里只是兜底防止未来实现变化
        });

      return closePromise;
    };

    const settleAndCleanup = async (
      type: "resolve" | "reject",
      payload: any
    ) => {
      // 停止当前任务的轮询
      if (checkTabCollectGoodsPolling) {
        checkTabCollectGoodsPolling.stop();
        checkTabCollectGoodsPolling = null;
      }
      // 清理端口引用
      port = null;

      await scheduleServiceWorkerClose();

      if (type === "resolve") {
        resolve(payload);
      } else {
        reject(payload);
      }
    };

    const safeReject = (error: Error) => {
      if (!isResolved) {
        const formatRejectResult = chunkItemList.map(
          ([key, value]: [string, any]) => {
            const { url } = value;
            return {
              asin: key,
              id: `${key}_${performance.now()}`,
              url,
              status: "fail",
              reason: "采集时标签意外关闭，无法知道采集发布是否成功",
              time: formatTime(),
            };
          }
        );
        collectResultList.push(...formatRejectResult);
        addCollectCountFailed(1);
        isResolved = true;
        settleAndCleanup("reject", error);
      }
    };

    const safeResolve = (result: any) => {
      if (!isResolved) {
        collectResultList.push(
          ...(result || []).map((item: any) => {
            const { status, asin, url, reason, id, time } = item;
            return {
              status,
              asin,
              url,
              reason,
              id,
              time,
            };
          })
        );

        isResolved = true;
        settleAndCleanup("resolve", result);
      }
    };

    const collectSiteUrl = data?.chunkItemList?.[0]?.[1]?.url;
    getTabIdByUrl(collectSiteUrl)
      .then(async (tabId) => {
        if (!tabId) {
          safeReject(new Error("暂无可以执行的tab"));
          cancelCollectChangeButtonHtml();
          return;
        }
        try {
          // 1. 与目标标签页的 content 建立长连接
          port = chrome.tabs.connect(tabId, {
            name: "background-to-content-collect-goods", // 连接名称，用于 content 识别
          });

          // 检查连接是否成功建立
          if (!port) {
            safeReject(new Error("连接对象创建失败"));
            return;
          }

          // 2. 为当前任务创建独立的轮询实例
          const checkTabCollectGoods = createCheckTabCollectGoods(
            tabId,
            port,
            safeReject
          );
          checkTabCollectGoodsPolling = new PollingManager(
            1000 * 5,
            checkTabCollectGoods
          );

          // 3. 监听连接断开（异常情况）
          // 注意：当调用 port.disconnect() 时，会触发此事件
          port.onDisconnect.addListener(() => {
            // 停止轮询
            if (checkTabCollectGoodsPolling) {
              checkTabCollectGoodsPolling.stop();
              checkTabCollectGoodsPolling = null;
            }

            // 清理端口引用
            port = null;

            // 只有在 Promise 还未 resolve/reject 时才调用 safeReject
            if (!isResolved) {
              const errorMessage = chrome.runtime.lastError
                ? chrome.runtime.lastError.message
                : "连接被断开";
              safeReject(new Error(`连接断开：${errorMessage}`));
            }
          });

          // 4. 监听 content 发送的处理结果（完成通知）
          port.onMessage.addListener((message: any) => {
            if (message.type === "COLLECT_GOODS_CONTENT_DONE") {
              // content 异步处理完成，resolve 结果
              safeResolve(message.result);
              // 主动断开连接（content 端可能已经断开，这里只是确保断开）
              if (port) {
                try {
                  port.disconnect();
                } catch (e) {
                  // 连接可能已经断开，忽略错误
                }
              }
            } else if (message.type === "COLLECT_GOODS_CONTENT_ERROR") {
              // content 处理出错
              safeReject(message.error || new Error("content 处理出错"));
              // 主动断开连接（content 端可能已经断开，这里只是确保断开）
              if (port) {
                try {
                  port.disconnect();
                } catch (e) {
                  // 连接可能已经断开，忽略错误
                }
              }
            }
          });

          // 5. 等待一小段时间确保连接建立，然后发送数据
          // 注意：chrome.tabs.connect 是同步的，但连接建立可能需要一点时间
          setTimeout(() => {
            // 检查连接是否仍然有效
            if (!port || isResolved) {
              return;
            }

            try {
              port.postMessage({
                type: "DO_COLLECT_GOODS",
                data,
              });

              // 检查 postMessage 是否成功
              if (chrome.runtime.lastError) {
                safeReject(
                  new Error(`发送消息失败：${chrome.runtime.lastError.message}`)
                );
                return;
              }

              // 6. 启动轮询检查标签页状态
              if (checkTabCollectGoodsPolling) {
                checkTabCollectGoodsPolling.start();
              }
            } catch (error) {
              safeReject(
                error instanceof Error
                  ? error
                  : new Error(`发送消息异常：${String(error)}`)
              );
            }
          }, 50); // 等待50ms确保连接建立
        } catch (error) {
          safeReject(error instanceof Error ? error : new Error(String(error)));
        }
      })
      .catch((error) => {
        safeReject(error instanceof Error ? error : new Error(String(error)));
      });
  });
}

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  const tabId = sender.tab?.id || 0;
  const abortController = abortControllerMap[tabId];
  const signal = abortController?.signal;
  if (request.action === "createCollectTaskApi") {
    // // TODO ZCH 调试
    // console.log(request.data);
    // sendResponse({
    //   code: 0,
    // });
    // return;

    fetch(`${BASE_URL}/goods-collect/commonData/insert/plusCollectGoods`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + request.token,
      },
      body: JSON.stringify({
        ...request.data,
        collectVersion: 2,
        version: chrome.runtime.getManifest().version,
      }),
      signal,
    })
      .then((res) => res.json())
      .then((data) => {
        sendResponse(data);
      })
      .catch((err) => {
        sendResponse({ error: err.message });
      });
    return true; // 保持消息通道开放
  } else if (request.action === "getHtml") {
    const { url } = request;

    Html.getHtmlNew(url, { signal }, (response) => {
      sendResponse({ data: response });
    });
    return true;
  } else if (request.action === "checkIsLogin") {
    fetch(`${BASE_URL}/user/user/getLoginInfo`, {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + request.token,
      },
      signal,
    })
      .then((res) => res.json())
      .then((data) => {
        if (Number(data.code) === 0) {
          sendResponse(true);
        } else {
          sendResponse(false);
        }
      })
      .catch(() => sendResponse(false));
    return true; // 保持消息通道开放
  } else if (request.action === "getOssUrl") {
    const { token, params } = request.data;
    getOssUrl({
      token,
      params,
      signal,
    })
      .then((data) => {
        sendResponse(data);
      })
      .catch((error) => {
        sendResponse({ error: error.message || "获取OSS URL失败" });
      });
    return true; // 保持消息通道开放
  } else if (request.action === "uploadSpuInfoInBackground") {
    fetch(request.api, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer token-shenzhucrwal",
      },
      body: JSON.stringify(request.data),
      signal,
    })
      .then((res) => res.json())
      .then(() => {
        sendResponse();
      })
      .catch((error) => sendResponse({ error: error || "上传失败" }));
    return true; // 保持消息通道开放
  } else if (request.action === "collectCurrentPage") {
    const { asinUrlMap, collectConfig } = request.data;
    collectCurrentPage({
      asinUrlMap,
      collectConfig,
      isRetry: false,
    });

    afterStartCollect();

    sendResponse({ success: true });
    return true; // 保持消息通道开放
  } else if (request.action === "doCancelCollectChangeButtonHtmlToBackground") {
    cancelCollectChangeButtonHtml();
    if (abortController) {
      abortController.abort();
      delete abortControllerMap[tabId];
    }
    sendResponse({ success: true });
  } else if (request.action === "doEndCollectChangeButtonHtmlToBackground") {
    endCollectChangeButtonHtml();
    sendResponse({ success: true });
  } else if (request.action === "doAddCollectCountFailedToBackground") {
    const { changeValue } = request.data;
    addCollectCountFailed(changeValue);
    sendResponse({ success: true });
  } else if (request.action === "doAddCollectCountCurrentToBackground") {
    const { changeValue } = request.data;
    addCollectCountCurrent(changeValue);
    sendResponse({ success: true });
  } else if (request.action === "doAddCollectCountSkippedToBackground") {
    const { changeValue } = request.data;
    addCollectCountSkipped(changeValue);
    sendResponse({ success: true });
  } else if (request.action === "contentInitCollect") {
    if (tabId) {
      if (!activeTabIds.includes(tabId)) {
        activeTabIds.push(tabId);
      }
      const controller = new AbortController();
      abortControllerMap[tabId] = controller;
      if (collectCountMap.total) {
        sendToContentScript({
          action: "changeCollectCount",
          data: {
            collectCountMap,
          },
        });
      }
    }
    sendResponse({ success: true });
  } else if (request.action === "startMultiKeywordCollect") {
    const { collectConfig, multiKeywordCollectData } = request.data || {};
    const { siteUrl, multiKeywordCollectionList } = multiKeywordCollectData;
    const url = `${siteUrl}/s?k=${multiKeywordCollectionList[0]}`;

    // 先立即发送响应，因为采集任务是长时间运行的后台任务，不需要等待完成
    sendResponse({ success: true });

    // 异步发送消息到 content script，不等待响应
    getTabIdByUrl(url)
      .then((tabId) => {
        if (!tabId) {
          throw new Error("未找到可用的采集标签页");
        }
        // 使用 sendMessage 但不等待响应，因为采集任务会长时间运行
        chrome.tabs.sendMessage(
          tabId,
          {
            action: "startMultiKeywordCollect",
            data: {
              collectConfig,
              multiKeywordCollectData,
            },
          },
          (response) => {
            // 这里只是检查消息是否成功发送，不等待采集任务完成
            if (chrome.runtime.lastError) {
              console.error(
                "发送采集消息失败:",
                chrome.runtime.lastError.message
              );
            } else {
              afterStartCollect();
            }
          }
        );
      })
      .catch((error) => {
        console.error("startMultiKeywordCollect 分发失败:", error);
      });
    return true; // 保持消息通道开放（虽然已经发送了响应，但这是最佳实践）
  } else if (request.action === "getCollectResultList") {
    sendResponse({ data: customDeepClone(collectResultList) });
    return true;
  } else if (request.action === "getTabId") {
    sendResponse({ tabId: sender?.tab?.id });
    return true;
  } else if (request.action === "collectPageUnload") {
    if (abortController) {
      abortController.abort();
      delete abortControllerMap[tabId];
    }
    sendResponse({ success: true });
  } else if (request.action === "retryCollectGoods") {
    chrome.storage.sync.get(["baoyiplus_collectConfig"]).then((storage) => {
      const { baoyiplus_collectConfig: collectConfig } = storage;
      const failCollectResult = request.data;
      const isStartCollect = collectCountMap.total > 0;
      const asinUrlMap: TAsinUrlMap = {};
      let failCount = 0;
      let skipCount = 0;
      const removeResultId: any[] = [];
      failCollectResult.forEach((result: any) => {
        const { asin, url, status, id } = result;
        asinUrlMap[asin] = {
          url,
          claimTemplate: collectConfig.claimTemplate,
        };
        removeResultId.push(id);
        if (status === "fail") {
          failCount++;
        } else if (status === "skip") {
          skipCount++;
        }
      });

      if (isStartCollect) {
        collectCountMap.failed -= failCount;
        collectCountMap.skipped -= skipCount;
        sendToContentScript({
          action: "changeCollectCount",
          data: {
            collectCountMap,
          },
        });
      } else {
        startCollectChangeButtonHtml();
      }

      collectCurrentPage({
        asinUrlMap,
        collectConfig,
        isRetry: isStartCollect,
      });

      collectResultList = collectResultList.filter(
        (item) => !removeResultId.includes(item.id)
      );
    });
    sendResponse({ success: true });
    return true; // 保持消息通道开放（因为上面有异步操作）
  } else if (request.action === "uploadLogToAliyun") {
    uploadLogToAliyun(request.data);
    sendResponse({ success: true });
  } else if (request.action === "getCollectCountMap") {
    sendResponse(customDeepClone(collectCountMap));
  }
});

chrome.action.onClicked.addListener(async (tab) => {
  if (!tab.id) {
    return;
  }

  // 检查是否支持 sidePanel API (Chrome 114+)
  if (chrome.sidePanel && chrome.sidePanel.open) {
    try {
      await chrome.sidePanel.open({
        tabId: tab.id,
      });
    } catch (error) {
      console.error("打开侧边栏失败:", error);
      console.error(
        "错误详情:",
        error instanceof Error ? error.message : error
      );
      // 降级方案：打开新标签页
      await chrome.tabs.create({
        url: chrome.runtime.getURL("index.html"),
      });
    }
  } else {
    // 低版本浏览器降级方案：打开新标签页
    try {
      await chrome.tabs.create({
        url: chrome.runtime.getURL("index.html"),
      });
    } catch (error) {
      console.error("打开新标签页失败:", error);
      console.error(
        "错误详情:",
        error instanceof Error ? error.message : error
      );
    }
  }
});

self.addEventListener("error", (event) => {
  try {
    const message = event?.message || event?.error;
    if (message) {
      uploadLogToAliyun([
        {
          type: "add-event-listener-error",
          message,
        },
      ]);
    }
  } catch {
    //
  }
});

const unhandledrejectionIgnoreMessage = [
  "Could not establish connection. Receiving end does not exist",
  "The page keeping the extension port is moved into back/forward cache, so the message channel is closed",
];
self.addEventListener("unhandledrejection", (event) => {
  try {
    const message = String(event.reason) || event.reason?.stack;
    if (message) {
      const isIgnoreMessage = unhandledrejectionIgnoreMessage.some(
        (ingoreMessage) => {
          message.includes(ingoreMessage);
        }
      );
      if (!isIgnoreMessage) {
        uploadLogToAliyun([
          {
            type: "unhandledrejection-error",
            message,
          },
        ]);
      }
    }
  } catch {
    //
  }
});
